package com.sunrise.configuracoes.repositorio;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.sunrise.configuracoes.repositorio.iface.PessoaDao;
import com.sunrise.generico.acesso.DaoService;
import com.sunrise.generico.entidade.Pessoa;
import com.sunrise.generico.entidade.TipoPessoa;
import com.sunrise.generico.visao.Filtro;

@Repository
public class PessoaDaoImpl extends DaoService<Pessoa> implements PessoaDao {

	public List<Pessoa> listarOrdenado() {
		List<Pessoa> list = listar(Pessoa.class);
		Collections.sort(list, new Comparator<Pessoa>() {

			@Override
			public int compare(Pessoa o1, Pessoa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	public List<Pessoa> search(Pessoa ex) {
		List<Pessoa> list = searchByExample(Pessoa.class, ex);
		Collections.sort(list, new Comparator<Pessoa>() {

			@Override
			public int compare(Pessoa o1, Pessoa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	public Pessoa getById(Long id) {
		return getById(id, Pessoa.class);
	}

	public List<Pessoa> searchByExample(Pessoa example) {
		List<Pessoa> list = searchByExample(Pessoa.class, example);
		Collections.sort(list, new Comparator<Pessoa>() {

			@Override
			public int compare(Pessoa o1, Pessoa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	public Pessoa buscarPorUsername(String userNome) {
		Criteria crit = getSession().createCriteria(Pessoa.class);
		crit.add(Restrictions.eq("username", userNome));
		return (Pessoa) crit.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Pessoa> listarPorNome(String nome) {
		Criteria crit = getSession().createCriteria(Pessoa.class);
		crit.add(Restrictions.ilike("nome", nome, MatchMode.ANYWHERE));
		return crit.list();
	}

	@Override
	public Pessoa buscarPorNome(String nome) {
		Criteria crit = getSession().createCriteria(Pessoa.class);
		crit.add(Restrictions.eq("nome", nome).ignoreCase());
		return (Pessoa) crit.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Pessoa> buscarPorFiltros(Filtro filtro) {
		Criteria crit = getSession().createCriteria(Pessoa.class);

		if (filtro.getTipoPessoa() != null && filtro.getTipoPessoa().getId() != null) {
			crit.createAlias("tiposPessoa", "tipo");
			crit.add(Restrictions.eq("tipo.id", filtro.getTipoPessoa().getId()));
		}

		if (filtro.getNome() != null && !filtro.getNome().isEmpty()) {
			crit.add(Restrictions.ilike("nome", filtro.getNome(), MatchMode.ANYWHERE));
		}
		if (filtro.getCpf() != null && !filtro.getCpf().isEmpty()) {
			crit.add(Restrictions.eq("cpf", filtro.getCpf()));
		}

		if (filtro.getCnpj() != null && !filtro.getCnpj().isEmpty()) {
			crit.add(Restrictions.eq("cnpj", filtro.getCnpj()));
		}

		if (filtro.getAtivo() != null) {
			crit.add(Restrictions.eq("ativo", filtro.getAtivo().getCodigo()));
		}

		crit.addOrder(Order.asc("nome"));
		return crit.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Collection<Pessoa> listarOrdenadoPorTipoPessoa(String tipoPessoa) {
		Criteria crit = getSession().createCriteria(Pessoa.class);
		crit.createAlias("tiposPessoa", "tipo");
		crit.add(Restrictions.eq("tipo.nome", tipoPessoa));

		List<Pessoa> list = crit.list();

		Collections.sort(list, new Comparator<Pessoa>() {

			@Override
			public int compare(Pessoa o1, Pessoa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Pessoa> listarPorNomeTipoPessoa(String nome, TipoPessoa tpPessoa) {
		Criteria crit = getSession().createCriteria(Pessoa.class);
		crit.createAlias("tiposPessoa", "tipo");
		crit.add(Restrictions.eq("tipo.nome", tpPessoa.getNome()));

		if (nome != null && !nome.isEmpty()) {
			crit.add(Restrictions.eq("nome", nome));
		}

		List<Pessoa> list = crit.list();

		Collections.sort(list, new Comparator<Pessoa>() {
			@Override
			public int compare(Pessoa o1, Pessoa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	@Override
	public Pessoa buscarPorCnpj(String cnpj) {
		Criteria crit = getSession().createCriteria(Pessoa.class);
		crit.add(Restrictions.eq("cnpj", cnpj));
		return (Pessoa) crit.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Pessoa> listarPorFiltrosComCelular(Filtro filtro) {
		Criteria crit = getSession().createCriteria(Pessoa.class);

		if (filtro.getNome() != null && !filtro.getNome().isEmpty()) {
			crit.add(Restrictions.ilike("nome", filtro.getNome(), MatchMode.ANYWHERE));
		}
		if (filtro.getCpf() != null && !filtro.getCpf().isEmpty()) {
			crit.add(Restrictions.eq("cpf", filtro.getCpf()));
		}

		if (filtro.getCnpj() != null && !filtro.getCnpj().isEmpty()) {
			crit.add(Restrictions.eq("cnpj", filtro.getCnpj()));
		}

		if (filtro.getDataInicio() != null && filtro.getDataFim() != null) {
			crit.add(Restrictions.between("dataCriacao", filtro.getDataInicio(), filtro.getDataFim()));
		} else if (filtro.getDataInicio() != null) {
			crit.add(Restrictions.ge("dataCriacao", filtro.getDataInicio()));
		} else if (filtro.getDataFim() != null) {
			crit.add(Restrictions.le("dataCriacao", filtro.getDataFim()));
		}

		crit.add(Restrictions.eq("ativo", Boolean.TRUE));

		crit.createAlias("contato", "cont");
		crit.add(Restrictions.isNotNull("cont.celular"));
		crit.addOrder(Order.asc("nome"));
		return crit.list();
	}

}
